package com.rookie.data.generate.util;


import com.rookie.data.generate.exception.AbortEndLabelException;
import com.rookie.data.generate.exception.RegException;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 正则生成表达式
 *
 * @author rookie
 */
public class RegularUtils {

    private static List<String> splitRegString(String str) {
        List<String> regList = new ArrayList<>();

        char[] chars = str.replaceAll(" ", "").toCharArray();
        int start = -2, end = -2;
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '[') {
                start = i;
            } else if (chars[i] == ']') {
                if (i < chars.length - 1 && chars[i + 1] == '{') {
                    end = searchEndLabel(chars, i + 1);
                } else {
                    end = i;
                }
                if (end == -1) {
                    throw new AbortEndLabelException("结束标签不匹配");
                }

                regList.add(String.valueOf(Arrays.copyOfRange(chars, start, end + 1)));
                i = end;
                start = -2;
            }
        }

        for (String s : regList) {
            if (!checkReg(s)) {
                throw new RegException(s + "配置的正则表达式不正确");
            }
        }
        return regList;
    }

    private static int searchEndLabel(char[] arr, int start) {
        for (int i = start; i < arr.length; i++) {
            if (arr[i] == '}') {
                return i;
            }
        }
        return -1;
    }

    private static boolean checkReg(String str) {
        if (str.replaceAll("\\[", "").length() < str.length() - 1) {
            return false;
        }
        if (str.replaceAll("]", "").length() < str.length() - 1) {
            return false;
        }
        if (str.replaceAll("\\{", "").length() < str.length() - 1) {
            return false;
        }
        return str.replaceAll("}", "").length() >= str.length() - 1;
    }

    private static boolean checkChildReg(String str) {
        if (str.contains("-") && str.length() == 3) {
            return true;
        }
        return str.length() == 1;
    }

    private static StringBuilder randomChar(int start, int end, int times) {
        StringBuilder stringBuilder = new StringBuilder();
        if (start > end) {
            int tmp = end;
            end = start;
            start = tmp;
        }
        for (int i = 0; i < times; i++) {
            if (start == end) {
                stringBuilder.append((char) start);
            } else {
                stringBuilder.append((char) GenerateUtils.random(start, end));
            }

        }
        return stringBuilder;
    }

    private static String generateChild(String reg) {
        String str = reg.substring(reg.indexOf("[") + 1, reg.indexOf("]"));
        int start = 1, end = 1;
        if (reg.contains("{")) {
            String numStr = reg.substring(reg.indexOf("{") + 1, reg.indexOf("}"));
            if (numStr.contains(",")) {
                String[] split = numStr.split(",");
                start = Integer.parseInt(split[0]);
                end = Integer.parseInt(split[1]);
            } else {
                start = end = Integer.parseInt(numStr);
            }
        }

        int randomNum = 0;
        if (start == end) {
            randomNum = start;
        } else {
            randomNum = GenerateUtils.random(start, end);
        }
        if (randomNum == 0) {
            return "";
        }

        String[] split = str.split("\\|");
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < split.length; i++) {
            if (randomNum == 0) {
                break;
            }

            if (!checkChildReg(split[i])) {
                throw new RegException(split[i] + "正则配置错误");
            }
            int random = 0;
            //            最后一次
            if (i == split.length - 1){
                random = randomNum;
            }else{
                random = GenerateUtils.random(0, randomNum);
            }

            if (split[i].contains("-")) {
                String[] splitStr = split[i].split("-");
                StringBuilder stringBuilder = randomChar(splitStr[0].charAt(0), splitStr[1].charAt(0), random);
                result.append(stringBuilder);
            } else {
                StringBuilder stringBuilder = randomChar(split[i].charAt(0), split[i].charAt(0), random);
                result.append(stringBuilder);
            }
            randomNum -= random;
        }
        return result.toString();
    }

    public static String generate(String reg) {
        if (StringUtils.isBlank(reg)){
            return "";
        }
        List<String> regList = splitRegString(reg);
        StringBuilder result = new StringBuilder();
        for (String s : regList) {
            String str = generateChild(s);
            result.append(str);
        }
        return result.toString();
    }
}
